package com.navi.mould1.service.impl;

import com.navi.bean.in.ConditionBean;
import com.navi.bean.out.activation_report.ActivationReportBean;
import com.navi.bean.out.activation_report.ActivationReportDataBean;
import com.navi.bean.out.activation_report.ActivationReportGridOut;
import com.navi.bean.sql.SqlVo;
import com.navi.mould1.reportUtils.LKingSortUtil;
import com.navi.mould1.pojo.TimestampPojo;
import com.navi.mould1.service.IActivationReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.navi.bean.sql.SqlVo.jointInSql;
import static com.navi.core.util.JdbcUtils.mySql_QueryRunner_QueryListBySql;
import static com.navi.mould1.reportUtils.ComputeUtil.getAverageRate;
import static com.navi.mould1.reportUtils.ComputeUtil.getRate;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.maxBy;
import static java.util.stream.Collectors.minBy;

@Slf4j
@Service
public class ActivationReportServiceImpl implements IActivationReportService {


    public ActivationReportBean getGridData(ConditionBean conditions) {
        final SqlVo sqlVo = new SqlVo();
        sqlVo.appendSql("SELECT");
        sqlVo.appendSql("b_1.data_desc AS fab_id,");
        sqlVo.appendSql("b_2.data_desc AS line_id,");
        sqlVo.appendSql("b_3.data_desc AS toolg_id,");
        sqlVo.appendSql("b_4.tool_dsc AS tool_id,");
        //sqlVo.appendSql("b_5.data_desc AS rsn_code_dsc,");
        sqlVo.appendSql("main_tab.*");
        sqlVo.appendSql("FROM (");
            sqlVo.appendSql("SELECT t.FAB_ID_FK, t.BAY_ID as LINE_ID_FK, g.TOOLG_ID as TOOLG_ID_FK, s.TOOL_ID_FK, s.TOOL_STAT, s.PV_TOOL_STAT, s.CLM_TIMESTAMP, s.PV_CLM_TIMESTAMP, s.RSN_CODE, s.RSN_CODE_DSC");
            sqlVo.appendSql("FROM his_icim_jn.his_ret_tool_st s");
            sqlVo.appendSql("LEFT JOIN icim_jn.bis_tool t on t.tool_id = s.tool_id_fk");
            sqlVo.appendSql("LEFT JOIN (select tool_id_fk, toolg_id from icim_jn.bis_tool_gr ) g on t.root_tool_id = g.tool_id_fk");
            //if (StringUtils.isNotEmpty(conditions.getTool_type())) sqlVo.appendSql("INNER JOIN (select tool_id from bis_tool where unit_typ='" + conditions.getTool_type() + "') E ON E.tool_id = s.tool_id_fk");
            sqlVo.appendSql("WHERE 1=1 ");
            //sqlVo.appendSql("and TOOL_CATE = 'PROC' and board_flg = 'Y'");
            if (StringUtils.isNotEmpty(conditions.getFab_id())) sqlVo.appendSql("AND s.TOOL_ID_FK IN(select tool_id from icim_jn.bis_tool where TOOL_CATE = 'PROC' and fab_id_fk in" + jointInSql(conditions.getFab_id()) + ")");
            if (StringUtils.isNotEmpty(conditions.getBay_id())) sqlVo.appendSql("AND s.TOOL_ID_FK IN(select tool_id from icim_jn.bis_tool where bay_id in" + jointInSql(conditions.getBay_id()) + ")");
            if (StringUtils.isNotEmpty(conditions.getToolg_id())) sqlVo.appendSql("AND s.TOOL_ID_FK IN(select tool_id from icim_jn.bis_tool where root_tool_id in (select tool_id_fk from icim_jn.bis_tool_gr where toolg_id in" + jointInSql(conditions.getToolg_id()) + "))");
            if (StringUtils.isNotEmpty(conditions.getTool_id())) sqlVo.appendSql("AND s.TOOL_ID_FK IN(select tool_id from icim_jn.bis_tool where tool_id in" + jointInSql(conditions.getTool_id()) + ")");
            if (StringUtils.isNotEmpty(conditions.getTool_type())) sqlVo.appendSql("AND s.TOOL_ID_FK IN(select tool_id from icim_jn.bis_tool where unit_typ = '" + conditions.getTool_type() + "')");
            if (StringUtils.isNotEmpty(conditions.getStart_time())) sqlVo.appendSqlAndAddParam("AND s.CLM_TIMESTAMP >= ? ", conditions.getStart_time());
            if (StringUtils.isNotEmpty(conditions.getEnd_time())) sqlVo.appendSqlAndAddParam("AND s.CLM_TIMESTAMP <= ? ", conditions.getEnd_time());
        sqlVo.appendSql(") main_tab");
        sqlVo.appendSql("LEFT JOIN (select data_ext,data_desc from icim_jn.bis_data where data_cate = 'FBID') b_1 ON main_tab.fab_id_fk = b_1.data_ext");
        sqlVo.appendSql("LEFT JOIN (select data_ext,data_desc from icim_jn.bis_data where data_cate = 'AREA') b_2 ON main_tab.line_id_fk = b_2.data_ext");
        sqlVo.appendSql("LEFT JOIN (select data_ext,data_desc from icim_jn.bis_data where data_cate = 'TOLG') b_3 ON main_tab.toolg_id_fk = b_3.data_ext");
        sqlVo.appendSql("LEFT JOIN (select tool_id,tool_dsc from icim_jn.bis_tool ) b_4 ON main_tab.tool_id_fk = b_4.tool_id");
        //sqlVo.appendSql("LEFT JOIN (select data_ext,data_desc from icim_jn.bis_data where data_cate = 'TSRC') b_5 ON main_tab.rsn_code = b_5.data_ext");

        List<ActivationReportDataBean> resultDataList = mySql_QueryRunner_QueryListBySql(sqlVo, ActivationReportDataBean.class);


        /*** 去除掉pv_timestamp > clm_timestamp的不正确数据。
         *   去除pv_clm_timestamp  pv_tool_timestamp  pv_tool_stat  tool_stat为空的不正确数据。**/
        resultDataList = resultDataList.stream()
                .filter(data -> data.getPv_clm_timestamp() != null)
                .filter(data -> data.getClm_timestamp() != null)
                .filter(data -> data.getPv_tool_stat() != null)
                .filter(data -> data.getTool_stat() != null)
                .filter(data -> !(data.getPv_clm_timestamp().getTime() > data.getClm_timestamp().getTime())).collect(Collectors.toList());

        Timestamp start_timestamp = Timestamp.valueOf(conditions.getStart_time());
        Timestamp end_timestamp = Timestamp.valueOf(conditions.getEnd_time());

        /*** 以Report选择 结束时间/开始时间 为分界点将数据切割、补全 **/
        List<ActivationReportDataBean> dataBean_1_List = new ArrayList<>();
        resultDataList.stream().collect(Collectors.groupingBy(ActivationReportDataBean::getTool_id)).forEach((tool, data_list) -> {
            ActivationReportDataBean maxClmTimeData = data_list.stream().collect(maxBy(comparing(data -> data.getClm_timestamp()))).get();
            //tool的最大时间数据的结束时间未到选定查询时间，则补全一笔数据
            if (maxClmTimeData.getClm_timestamp().before(end_timestamp)) {
                ActivationReportDataBean dataBean = new ActivationReportDataBean();
                org.springframework.beans.BeanUtils.copyProperties(maxClmTimeData, dataBean);
                dataBean.setPv_tool_stat(maxClmTimeData.getTool_stat());
                dataBean.setPv_clm_timestamp(maxClmTimeData.getClm_timestamp());
                dataBean.setClm_timestamp(end_timestamp);
                data_list.add(dataBean);
            }
            ActivationReportDataBean minPvClmTimeData = data_list.stream().collect(minBy(comparing(data -> data.getPv_clm_timestamp()))).get();
            //tool的最小时间数据的开始时间未到选定查询时间，则修改这一笔数据的开始时间
            if (minPvClmTimeData.getPv_clm_timestamp().before(start_timestamp)) {
                ActivationReportDataBean dataBean = new ActivationReportDataBean();
                org.springframework.beans.BeanUtils.copyProperties(minPvClmTimeData, dataBean);
                dataBean.setPv_clm_timestamp(start_timestamp);
                data_list.remove(minPvClmTimeData);
                data_list.add(dataBean);
            }
            dataBean_1_List.addAll(data_list);
        });

        /*** 以每天08:00为分界点切割为多个时间段数据 **/
        List<ActivationReportDataBean> dataBean_2_List = new ArrayList<>();
        dataBean_1_List.forEach(data -> {
            splitTimestamp(data.getPv_clm_timestamp(), data.getClm_timestamp()).forEach(timestampPojo ->{
                ActivationReportDataBean dataBean = new ActivationReportDataBean();
                org.springframework.beans.BeanUtils.copyProperties(data, dataBean);
                dataBean.setPv_clm_timestamp(timestampPojo.getStartTiemstamp());
                dataBean.setClm_timestamp(timestampPojo.getEndTimestamp());
                //过滤掉持续时间为0的数据 例: 2018-10-14 08:00:00 --- 2018-10-14 08:00:00   &&   过滤掉pv_clm_timestamp早于start时间的数据
                if ((data.getClm_timestamp().getTime() - data.getPv_clm_timestamp().getTime() != 0) && (dataBean.getPv_clm_timestamp().getTime() >= start_timestamp.getTime())){
                    dataBean_2_List.add(dataBean);
                }
            });
        });

        /*** 数据赋值-By天**/
        dataBean_2_List.forEach(data -> {
            if ((data.getClm_timestamp().getHours()*3600 + data.getClm_timestamp().getMinutes()*60 + data.getClm_timestamp().getSeconds()*1) <= (8*3600)) {
                Calendar cc = Calendar.getInstance();
                cc.setTime(data.getClm_timestamp());
                cc.add(Calendar.DAY_OF_MONTH, -1);
                data.setDay(new SimpleDateFormat("yyyy-MM-dd").format(cc.getTime()));
            }else {
                data.setDay(data.getClm_timestamp().toString().substring(0, 10));
            }
        });

        /**** where条件 供Grid表格跳转抓群明细数据 **/
        if (StringUtils.isNotEmpty(conditions.getDay())) {
            String day = conditions.getDay();
            List<ActivationReportDataBean> dataBeanList = dataBean_2_List.stream().filter(data -> StringUtils.isNotEmpty(day)).filter(data -> day.equals(data.getDay())).collect(Collectors.toList());
            dataBean_2_List.clear();
            dataBean_2_List.addAll(dataBeanList);
        }

        /*** By Day --- By Tool 计算状态、时长信息、所占百分比 **/
        List<ActivationReportGridOut> gridOutBean_by_tool_List = new ArrayList<>();
        List<ActivationReportGridOut> gridOutBean_by_tool_rsnCodeDsc_List = new ArrayList<>();
        dataBean_2_List.stream().collect(Collectors.groupingBy(ActivationReportDataBean::getDay)).forEach((day, by_day_list) -> {
            //计算每天的total时间(分母)
            Long totalSecond_temp = null;
            String start_day = start_timestamp.toString().substring(0, 10);
            if ((start_timestamp.getHours()*3600 + start_timestamp.getMinutes()*60 + start_timestamp.getSeconds()*1) <= (8*3600)) {
                Calendar cc = Calendar.getInstance();
                cc.setTime(start_timestamp);
                cc.add(Calendar.DAY_OF_MONTH, -1);
                start_day = new SimpleDateFormat("yyyy-MM-dd").format(cc.getTime());
            }
            String end_day = end_timestamp.toString().substring(0, 10);
            if ((end_timestamp.getHours()*3600 + end_timestamp.getMinutes()*60 + end_timestamp.getSeconds()*1) <= (8*3600)) {
                Calendar cc = Calendar.getInstance();
                cc.setTime(end_timestamp);
                cc.add(Calendar.DAY_OF_MONTH, -1);
                end_day = new SimpleDateFormat("yyyy-MM-dd").format(cc.getTime());
            }
            if (start_day.equals(day) && end_day.equals(day)){
                totalSecond_temp = (end_timestamp.getTime() - start_timestamp.getTime()) / 1000;
            }else if (!start_day.equals(day) && !end_day.equals(day)){
                totalSecond_temp = (long)24 * 60 * 60;
            }else if (start_day.equals(day) && !end_day.equals(day)){
                totalSecond_temp = ((Timestamp.valueOf(day + " 08:00:00").getTime() + 24*60*60*1000 - start_timestamp.getTime()) /1000);
            }else if (!start_day.equals(day) && end_day.equals(day)){
                totalSecond_temp = ((end_timestamp.getTime() - Timestamp.valueOf(day + " 08:00:00").getTime()) /1000);
            }
            final Long totalSecond = totalSecond_temp;

            by_day_list.stream().filter(data -> data.getTool_id() != null).collect(Collectors.groupingBy(ActivationReportDataBean::getTool_id)).forEach((tool, by_day_tool_list) -> {
                List<ActivationReportDataBean> dataBean_list = new ArrayList<>();
                by_day_tool_list.stream().filter(data -> data.getPv_tool_stat() != null).collect(Collectors.groupingBy(ActivationReportDataBean::getPv_tool_stat)).forEach((pvStat, by_day_tool_pvStat_list) -> {
                    ActivationReportDataBean dataBean = new ActivationReportDataBean();
                    dataBean.setPv_tool_stat(pvStat);
                    dataBean.setSecond_time(by_day_tool_pvStat_list.stream().mapToLong(data -> (data.getClm_timestamp().getTime() - data.getPv_clm_timestamp().getTime()) / 1000).sum());
                    dataBean_list.add(dataBean);

                    //Tool - 的详细原因代码
                    by_day_tool_pvStat_list.stream().filter(data -> StringUtils.isNotEmpty(data.getRsn_code_dsc())).collect(Collectors.groupingBy(ActivationReportDataBean::getRsn_code_dsc)).forEach((rsnCodeDsc, by_day_tool_pvStat_RsnCodeDsc_list) -> {
                        ActivationReportGridOut gridOutBean2 = new ActivationReportGridOut();
                        gridOutBean2.setTotal_second(totalSecond);
                        gridOutBean2.setRsnCodeDsc_stat(pvStat);
                        gridOutBean2.setRsnCode(by_day_tool_pvStat_RsnCodeDsc_list.get(0).getRsn_code());
                        gridOutBean2.setRsnCodeDsc(rsnCodeDsc);
                        gridOutBean2.setRsnCodeDsc_second(by_day_tool_pvStat_RsnCodeDsc_list.stream().mapToLong(data -> (data.getClm_timestamp().getTime() - data.getPv_clm_timestamp().getTime()) / 1000).sum());
                        gridOutBean2.setRsnCodeDsc_rate(getRate(gridOutBean2.getRsnCodeDsc_second(), gridOutBean2.getTotal_second()));
                        gridOutBean2.setDay(day);
                        gridOutBean2.setFab_id(by_day_tool_pvStat_list.get(0).getFab_id());
                        gridOutBean2.setFab_id_fk(by_day_tool_pvStat_list.get(0).getFab_id_fk());
                        gridOutBean2.setLine_id(by_day_tool_pvStat_list.get(0).getLine_id());
                        gridOutBean2.setLine_id_fk(by_day_tool_pvStat_list.get(0).getLine_id_fk());
                        gridOutBean2.setToolg_id(by_day_tool_pvStat_list.get(0).getToolg_id());
                        gridOutBean2.setToolg_id_fk(by_day_tool_pvStat_list.get(0).getToolg_id_fk());
                        gridOutBean2.setTool_id(by_day_tool_pvStat_list.get(0).getTool_id());
                        gridOutBean2.setTool_id_fk(by_day_tool_pvStat_list.get(0).getTool_id_fk());
                        gridOutBean2.rate2Percent();
                        gridOutBean2.computeTotalTime();
                        gridOutBean_by_tool_rsnCodeDsc_List.add(gridOutBean2);
                    });
                });

                //各状态稼动率所占时长/百分比
                ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
                gridOutBean.setTotal_second(totalSecond);
                dataBean_list.forEach(data -> {
                    if ("RUN".equalsIgnoreCase(data.getPv_tool_stat())) {
                        gridOutBean.setRun_second(data.getSecond_time());
                        gridOutBean.setRun_rate(getRate(data.getSecond_time(), gridOutBean.getTotal_second()));
                    }else if ("DOWN".equalsIgnoreCase(data.getPv_tool_stat())) {
                        gridOutBean.setDown_second(data.getSecond_time());
                        gridOutBean.setDown_rate(getRate(data.getSecond_time(), gridOutBean.getTotal_second()));
                    }else if ("IDLE".equalsIgnoreCase(data.getPv_tool_stat())) {
                        gridOutBean.setIdle_second(data.getSecond_time());
                        gridOutBean.setIdle_rate(getRate(data.getSecond_time(), gridOutBean.getTotal_second()));
                    }else if ("PM".equalsIgnoreCase(data.getPv_tool_stat())) {
                        gridOutBean.setPm_second(data.getSecond_time());
                        gridOutBean.setPm_rate(getRate(data.getSecond_time(), gridOutBean.getTotal_second()));
                    }else if ("STOP".equalsIgnoreCase(data.getPv_tool_stat())) {
                        gridOutBean.setStop_second(data.getSecond_time());
                        gridOutBean.setStop_rate(getRate(data.getSecond_time(), gridOutBean.getTotal_second()));
                    }else if ("OTHER".equalsIgnoreCase(data.getPv_tool_stat())) {
                        gridOutBean.setOther_second(data.getSecond_time());
                        gridOutBean.setOther_rate(getRate(data.getSecond_time(), gridOutBean.getTotal_second()));
                    }
                });
                gridOutBean.setActivation_rate(getRate(gridOutBean.getRun_second(), (gridOutBean.getTotal_second() - gridOutBean.getStop_second())));
                gridOutBean.setDay(day);
                gridOutBean.setFab_id(by_day_tool_list.get(0).getFab_id());
                gridOutBean.setLine_id(by_day_tool_list.get(0).getLine_id());
                gridOutBean.setToolg_id(by_day_tool_list.get(0).getToolg_id());
                gridOutBean.setTool_id(by_day_tool_list.get(0).getTool_id());
                gridOutBean.setFab_id_fk(by_day_tool_list.get(0).getFab_id_fk());
                gridOutBean.setLine_id_fk(by_day_tool_list.get(0).getLine_id_fk());
                gridOutBean.setToolg_id_fk(by_day_tool_list.get(0).getToolg_id_fk());
                gridOutBean.setTool_id_fk(by_day_tool_list.get(0).getTool_id_fk());
                gridOutBean.rate2Percent();
                gridOutBean.computeTotalTime();
                gridOutBean_by_tool_List.add(gridOutBean);
            });
        });
        LKingSortUtil.sort(gridOutBean_by_tool_List, new String[] { "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { false, true, true, true, true });

        /*** 计算Toolg的工时分布比例 **/
        List<ActivationReportGridOut> gridOutBean_by_toolg_List = new ArrayList<>();
        List<ActivationReportGridOut> gridOutBean_by_toolg_rsnCodeDsc_List = new ArrayList<>();
        if (true) {
            gridOutBean_by_tool_List.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getDay)).forEach((day, by_day_list) -> {
                by_day_list.stream().filter(data -> data.getToolg_id() != null).collect(Collectors.groupingBy(ActivationReportGridOut::getToolg_id)).forEach((toolg, by_day_toolg_list) -> {
                    ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
                    by_day_toolg_list.forEach(data -> {
                        gridOutBean.setRun_rate(gridOutBean.getRun_rate() + data.getRun_rate());
                        gridOutBean.setDown_rate(gridOutBean.getDown_rate() + data.getDown_rate());
                        gridOutBean.setIdle_rate(gridOutBean.getIdle_rate() + data.getIdle_rate());
                        gridOutBean.setPm_rate(gridOutBean.getPm_rate() + data.getPm_rate());
                        gridOutBean.setStop_rate(gridOutBean.getStop_rate() + data.getStop_rate());
                        gridOutBean.setOther_rate(gridOutBean.getOther_rate() + data.getOther_rate());
                        gridOutBean.setActivation_rate(gridOutBean.getActivation_rate() + data.getActivation_rate());
                        gridOutBean.setRun_second(gridOutBean.getRun_second() + data.getRun_second());
                        gridOutBean.setDown_second(gridOutBean.getDown_second() + data.getDown_second());
                        gridOutBean.setIdle_second(gridOutBean.getIdle_second() + data.getIdle_second());
                        gridOutBean.setPm_second(gridOutBean.getPm_second() + data.getPm_second());
                        gridOutBean.setStop_second(gridOutBean.getStop_second() + data.getStop_second());
                        gridOutBean.setOther_second(gridOutBean.getOther_second() + data.getOther_second());
                        gridOutBean.setTotal_second(gridOutBean.getTotal_second() + data.getTotal_second());
                    });
                    gridOutBean.setDay(day);
                    gridOutBean.setFab_id(by_day_toolg_list.get(0).getFab_id());
                    gridOutBean.setToolg_id(toolg);
                    gridOutBean.setFab_id_fk(by_day_toolg_list.get(0).getFab_id_fk());
                    gridOutBean.setToolg_id_fk(by_day_toolg_list.get(0).getToolg_id_fk());
                    gridOutBean.setRun_rate(getAverageRate(gridOutBean.getRun_rate(), by_day_toolg_list.size()));
                    gridOutBean.setDown_rate(getAverageRate(gridOutBean.getDown_rate(), by_day_toolg_list.size()));
                    gridOutBean.setIdle_rate(getAverageRate(gridOutBean.getIdle_rate(), by_day_toolg_list.size()));
                    gridOutBean.setPm_rate(getAverageRate(gridOutBean.getPm_rate(), by_day_toolg_list.size()));
                    gridOutBean.setStop_rate(getAverageRate(gridOutBean.getStop_rate(), by_day_toolg_list.size()));
                    gridOutBean.setOther_rate(getAverageRate(gridOutBean.getOther_rate(), by_day_toolg_list.size()));
                    gridOutBean.setActivation_rate(getAverageRate(gridOutBean.getActivation_rate(), by_day_toolg_list.size()));
                    gridOutBean.rate2Percent();
                    gridOutBean.computeTotalTime();
                    gridOutBean_by_toolg_List.add(gridOutBean);
                });
            });
            LKingSortUtil.sort(gridOutBean_by_toolg_List, new String[] { "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { false, true, true, true, true });

            //Toolg - 的详细原因代码
            gridOutBean_by_tool_rsnCodeDsc_List.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getDay)).forEach((day, by_day_list) -> {
                by_day_list.stream().filter(data -> data.getToolg_id() != null).collect(Collectors.groupingBy(ActivationReportGridOut::getToolg_id)).forEach((toolg, by_day_toolg_list) -> {

                    by_day_toolg_list.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getRsnCodeDsc)).forEach((rsnCodeDsc, by_day_toolg_rnsCodeDsc_list) -> {
                        ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
                        gridOutBean.setRsnCodeDsc_stat(by_day_toolg_rnsCodeDsc_list.get(0).getRsnCodeDsc_stat());
                        gridOutBean.setRsnCode(by_day_toolg_rnsCodeDsc_list.get(0).getRsnCode());
                        gridOutBean.setRsnCodeDsc(rsnCodeDsc);
                        gridOutBean.setRsnCodeDsc_rate(getAverageRate(by_day_toolg_rnsCodeDsc_list.stream().mapToDouble(data -> data.getRsnCodeDsc_rate()).sum(), by_day_toolg_list.size()));
                        //gridOutBean.setRsnCodeDsc_rate(by_day_toolg_rnsCodeDsc_list.stream().mapToDouble(data -> data.getRsnCodeDsc_rate()).sum());
                        gridOutBean.setRsnCodeDsc_second(by_day_toolg_rnsCodeDsc_list.stream().mapToLong(data -> data.getRsnCodeDsc_second()).sum());
                        gridOutBean.setDay(day);
                        gridOutBean.setFab_id(by_day_toolg_rnsCodeDsc_list.get(0).getFab_id());
                        gridOutBean.setFab_id_fk(by_day_toolg_rnsCodeDsc_list.get(0).getFab_id_fk());
                        gridOutBean.setToolg_id(toolg);
                        gridOutBean.setToolg_id_fk(by_day_toolg_rnsCodeDsc_list.get(0).getToolg_id_fk());
                        gridOutBean.rate2Percent();
                        gridOutBean.computeTotalTime();
                        gridOutBean_by_toolg_rsnCodeDsc_List.add(gridOutBean);
                    });
                });
            });
        }

        /*** 计算Line的工时分布比例 **/
        List<ActivationReportGridOut> gridOutBean_by_line_List = new ArrayList<>();
        List<ActivationReportGridOut> gridOutBean_by_line_rsnCodeDsc_List = new ArrayList<>();
        if (true) {
            gridOutBean_by_tool_List.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getDay)).forEach((day, by_day_list) -> {
                by_day_list.stream().filter(data -> data.getLine_id() != null).collect(Collectors.groupingBy(ActivationReportGridOut::getLine_id)).forEach((line, by_day_line_list) -> {
                    ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
                    by_day_line_list.forEach(data -> {
                        gridOutBean.setRun_rate(gridOutBean.getRun_rate() + data.getRun_rate());
                        gridOutBean.setDown_rate(gridOutBean.getDown_rate() + data.getDown_rate());
                        gridOutBean.setIdle_rate(gridOutBean.getIdle_rate() + data.getIdle_rate());
                        gridOutBean.setPm_rate(gridOutBean.getPm_rate() + data.getPm_rate());
                        gridOutBean.setStop_rate(gridOutBean.getStop_rate() + data.getStop_rate());
                        gridOutBean.setOther_rate(gridOutBean.getOther_rate() + data.getOther_rate());
                        gridOutBean.setActivation_rate(gridOutBean.getActivation_rate() + data.getActivation_rate());
                        gridOutBean.setRun_second(gridOutBean.getRun_second() + data.getRun_second());
                        gridOutBean.setDown_second(gridOutBean.getDown_second() + data.getDown_second());
                        gridOutBean.setIdle_second(gridOutBean.getIdle_second() + data.getIdle_second());
                        gridOutBean.setPm_second(gridOutBean.getPm_second() + data.getPm_second());
                        gridOutBean.setStop_second(gridOutBean.getStop_second() + data.getStop_second());
                        gridOutBean.setOther_second(gridOutBean.getOther_second() + data.getOther_second());
                        gridOutBean.setTotal_second(gridOutBean.getTotal_second() + data.getTotal_second());
                    });
                    gridOutBean.setDay(day);
                    gridOutBean.setFab_id(by_day_line_list.get(0).getFab_id());
                    gridOutBean.setLine_id(line);
                    gridOutBean.setFab_id_fk(by_day_line_list.get(0).getFab_id_fk());
                    gridOutBean.setLine_id_fk(by_day_line_list.get(0).getLine_id_fk());
                    gridOutBean.setRun_rate(getAverageRate(gridOutBean.getRun_rate(), by_day_line_list.size()));
                    gridOutBean.setDown_rate(getAverageRate(gridOutBean.getDown_rate(), by_day_line_list.size()));
                    gridOutBean.setIdle_rate(getAverageRate(gridOutBean.getIdle_rate(), by_day_line_list.size()));
                    gridOutBean.setPm_rate(getAverageRate(gridOutBean.getPm_rate(), by_day_line_list.size()));
                    gridOutBean.setStop_rate(getAverageRate(gridOutBean.getStop_rate(), by_day_line_list.size()));
                    gridOutBean.setOther_rate(getAverageRate(gridOutBean.getOther_rate(), by_day_line_list.size()));
                    gridOutBean.setActivation_rate(getAverageRate(gridOutBean.getActivation_rate(), by_day_line_list.size()));
                    gridOutBean.rate2Percent();
                    gridOutBean.computeTotalTime();
                    gridOutBean_by_line_List.add(gridOutBean);
                });
            });
            LKingSortUtil.sort(gridOutBean_by_line_List, new String[] { "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { false, true, true, true, true });

            //Line - 的详细原因代码
            gridOutBean_by_tool_rsnCodeDsc_List.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getDay)).forEach((day, by_day_list) -> {
                by_day_list.stream().filter(data -> data.getLine_id() != null).collect(Collectors.groupingBy(ActivationReportGridOut::getLine_id)).forEach((line, by_day_line_list) -> {
                    by_day_line_list.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getRsnCodeDsc)).forEach((rsnCodeDsc, by_day_line_rnsCodeDsc_list) -> {
                        ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
                        gridOutBean.setRsnCodeDsc_stat(by_day_line_rnsCodeDsc_list.get(0).getRsnCodeDsc_stat());
                        gridOutBean.setRsnCode(by_day_line_rnsCodeDsc_list.get(0).getRsnCode());
                        gridOutBean.setRsnCodeDsc(rsnCodeDsc);
                        gridOutBean.setRsnCodeDsc_rate(getAverageRate(by_day_line_rnsCodeDsc_list.stream().mapToDouble(data -> data.getRsnCodeDsc_rate()).sum(), by_day_line_list.size()));
                        //gridOutBean.setRsnCodeDsc_rate(by_day_line_rnsCodeDsc_list.stream().mapToDouble(data -> data.getRsnCodeDsc_rate()).sum());
                        gridOutBean.setRsnCodeDsc_second(by_day_line_rnsCodeDsc_list.stream().mapToLong(data -> data.getRsnCodeDsc_second()).sum());
                        gridOutBean.setDay(day);
                        gridOutBean.setFab_id(by_day_line_rnsCodeDsc_list.get(0).getFab_id());
                        gridOutBean.setFab_id_fk(by_day_line_rnsCodeDsc_list.get(0).getFab_id_fk());
                        gridOutBean.setLine_id(line);
                        gridOutBean.setLine_id_fk(by_day_line_rnsCodeDsc_list.get(0).getLine_id_fk());
                        gridOutBean.rate2Percent();
                        gridOutBean.computeTotalTime();
                        gridOutBean_by_line_rsnCodeDsc_List.add(gridOutBean);
                    });
                });
            });
        }

        /*** 计算Fab的工时分布比例 **/
        List<ActivationReportGridOut> gridOutBean_by_fab_List = new ArrayList<>();
        if (true) {
            gridOutBean_by_tool_List.stream().collect(Collectors.groupingBy(ActivationReportGridOut::getDay)).forEach((day, by_day_list) -> {
                by_day_list.stream().filter(data -> data.getFab_id() != null).collect(Collectors.groupingBy(ActivationReportGridOut::getFab_id)).forEach((fab, by_day_fab_list) -> {
                    ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
                    by_day_fab_list.forEach(data -> {
                        gridOutBean.setRun_rate(gridOutBean.getRun_rate() + data.getRun_rate());
                        gridOutBean.setDown_rate(gridOutBean.getDown_rate() + data.getDown_rate());
                        gridOutBean.setIdle_rate(gridOutBean.getIdle_rate() + data.getIdle_rate());
                        gridOutBean.setPm_rate(gridOutBean.getPm_rate() + data.getPm_rate());
                        gridOutBean.setStop_rate(gridOutBean.getStop_rate() + data.getStop_rate());
                        gridOutBean.setOther_rate(gridOutBean.getOther_rate() + data.getOther_rate());
                        gridOutBean.setActivation_rate(gridOutBean.getActivation_rate() + data.getActivation_rate());
                        gridOutBean.setRun_second(gridOutBean.getRun_second() + data.getRun_second());
                        gridOutBean.setDown_second(gridOutBean.getDown_second() + data.getDown_second());
                        gridOutBean.setIdle_second(gridOutBean.getIdle_second() + data.getIdle_second());
                        gridOutBean.setPm_second(gridOutBean.getPm_second() + data.getPm_second());
                        gridOutBean.setStop_second(gridOutBean.getStop_second() + data.getStop_second());
                        gridOutBean.setOther_second(gridOutBean.getOther_second() + data.getOther_second());
                        gridOutBean.setTotal_second(gridOutBean.getTotal_second() + data.getTotal_second());
                    });
                    gridOutBean.setDay(day);
                    gridOutBean.setFab_id(fab);
                    gridOutBean.setFab_id_fk(by_day_fab_list.get(0).getFab_id_fk());
                    gridOutBean.setRun_rate(getAverageRate(gridOutBean.getRun_rate(), by_day_fab_list.size()));
                    gridOutBean.setDown_rate(getAverageRate(gridOutBean.getDown_rate(), by_day_fab_list.size()));
                    gridOutBean.setIdle_rate(getAverageRate(gridOutBean.getIdle_rate(), by_day_fab_list.size()));
                    gridOutBean.setPm_rate(getAverageRate(gridOutBean.getPm_rate(), by_day_fab_list.size()));
                    gridOutBean.setStop_rate(getAverageRate(gridOutBean.getStop_rate(), by_day_fab_list.size()));
                    gridOutBean.setOther_rate(getAverageRate(gridOutBean.getOther_rate(), by_day_fab_list.size()));
                    gridOutBean.setActivation_rate(getAverageRate(gridOutBean.getActivation_rate(), by_day_fab_list.size()));
                    gridOutBean.rate2Percent();
                    gridOutBean.computeTotalTime();
                    gridOutBean_by_fab_List.add(gridOutBean);
                });
            });
            LKingSortUtil.sort(gridOutBean_by_fab_List, new String[] { "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { true, true, true, true, true });
        }

        /*** 计算Tool的稼动率排行 **/
        List<ActivationReportGridOut> gridOutBean_by_toolRateRank_List = new ArrayList<>();
        gridOutBean_by_tool_List.stream().forEach(data -> {
            ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
            gridOutBean.setDay(data.getDay());
            gridOutBean.setTool_id(data.getTool_id());
            gridOutBean.setTool_id_fk(data.getTool_id_fk());
            gridOutBean.setRun_rate(data.getRun_rate());
            gridOutBean.setActivation_rate(data.getActivation_rate());
            gridOutBean.setTotal_second(data.getTotal_second());
            gridOutBean.rate2Percent();
            gridOutBean.computeTotalTime();
            gridOutBean_by_toolRateRank_List.add(gridOutBean);
        });
        LKingSortUtil.sort(gridOutBean_by_toolRateRank_List, new String[] { "run_rate", "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { false, true, true, true, true, true });

        /*** 计算Toolg的稼动率排行 **/
        List<ActivationReportGridOut> gridOutBean_by_toolgRateRank_List = new ArrayList<>();
        gridOutBean_by_toolg_List.stream().forEach(data -> {
            ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
            gridOutBean.setDay(data.getDay());
            gridOutBean.setToolg_id(data.getToolg_id());
            gridOutBean.setToolg_id_fk(data.getToolg_id_fk());
            gridOutBean.setRun_rate(data.getRun_rate());
            gridOutBean.setActivation_rate(data.getActivation_rate());
            gridOutBean.setTotal_second(data.getTotal_second());
            gridOutBean.rate2Percent();
            gridOutBean.computeTotalTime();
            gridOutBean_by_toolgRateRank_List.add(gridOutBean);
        });
        LKingSortUtil.sort(gridOutBean_by_toolgRateRank_List, new String[] { "run_rate", "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { false, true, true, true, true, true });

        /*** 计算Line的稼动率排行 **/
        List<ActivationReportGridOut> gridOutBean_by_lineRateRank_List = new ArrayList<>();
        gridOutBean_by_line_List.stream().forEach(data -> {
            ActivationReportGridOut gridOutBean = new ActivationReportGridOut();
            gridOutBean.setDay(data.getDay());
            gridOutBean.setLine_id(data.getLine_id());
            gridOutBean.setLine_id_fk(data.getLine_id_fk());
            gridOutBean.setRun_rate(data.getRun_rate());
            gridOutBean.setActivation_rate(data.getActivation_rate());
            gridOutBean.setTotal_second(data.getTotal_second());
            gridOutBean.rate2Percent();
            gridOutBean.computeTotalTime();
            gridOutBean_by_lineRateRank_List.add(gridOutBean);
        });
        LKingSortUtil.sort(gridOutBean_by_lineRateRank_List, new String[] { "run_rate", "day", "fab_id", "line_id", "toolg_id", "tool_id" }, new boolean[] { false, true, true, true, true, true });



        /****************************************************************************/
        ActivationReportBean reportBean = new ActivationReportBean();
        reportBean.setLine_rateRank_gridData(gridOutBean_by_lineRateRank_List);
        reportBean.setToolg_rateRank_gridData(gridOutBean_by_toolgRateRank_List);
        reportBean.setTool_rateRank_gridData(gridOutBean_by_toolRateRank_List);
        reportBean.setFab_gridData(gridOutBean_by_fab_List);
        reportBean.setLine_gridData(gridOutBean_by_line_List);
        reportBean.setLine_rsnCodeDsc_gridData(gridOutBean_by_line_rsnCodeDsc_List);
        reportBean.setToolg_gridData(gridOutBean_by_toolg_List);
        reportBean.setToolg_rsnCodeDsc_gridData(gridOutBean_by_toolg_rsnCodeDsc_List);
        reportBean.setTool_gridData(gridOutBean_by_tool_List);
        reportBean.setTool_rsnCodeDsc_gridData(gridOutBean_by_tool_rsnCodeDsc_List);
        return reportBean;
    }








    /*** 切割Timestamp时间段 **/
    private List<TimestampPojo> splitTimestamp(Timestamp start_timestamp, Timestamp end_timestamp) {
        List<TimestampPojo> timestampList = new ArrayList<TimestampPojo>();
        Timestamp b_timestamp = Timestamp.valueOf(start_timestamp.toString().substring(0, 10) + " 08:00:00");
        while (true) {
            // start、end 等于、早于限定时间
            if (start_timestamp.before(b_timestamp) && end_timestamp.before(b_timestamp)){
                timestampList.add(new TimestampPojo(start_timestamp, end_timestamp));
                break;
            // start 比限定时间早、end 等于、晚于限定时间
            }else if (start_timestamp.before(b_timestamp) && end_timestamp.after(b_timestamp)){
                timestampList.add(new TimestampPojo(start_timestamp, b_timestamp));
                start_timestamp = b_timestamp;
            }
            // 限定时间加一天
            Calendar cc = Calendar.getInstance();
            cc.setTime(b_timestamp);
            cc.add(Calendar.DAY_OF_MONTH, 1);
            b_timestamp = Timestamp.valueOf(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cc.getTime()));
        }
        return timestampList;
    }


}
